﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Ue.Eagle.Runtime.FileSystems.Dependencies;
using Ue.Eagle.Runtime.Models;

namespace Ue.Eagle.Runtime.Loaders
{
    public abstract class PluginLoaderBase : IPluginLoader
    {
        private readonly IDependenciesFolder dependenciesFolder;

        public PluginLoaderBase(IDependenciesFolder dependenciesFolder)
        {
            this.dependenciesFolder = dependenciesFolder;
        }

        public abstract int Priority { get; }
        public string Name { get { return this.GetType().Name; } }

        public virtual IEnumerable<PluginReferenceProbeEntry> ProbeReferences(PluginDescriptor PluginDescriptor)
        {
            return Enumerable.Empty<PluginReferenceProbeEntry>();
        }

        public virtual Assembly LoadReference(DependencyReferenceDescriptor reference)
        {
            return null;
        }

        public virtual bool IsCompatibleWithModuleReferences(PluginDescriptor extension, IEnumerable<PluginProbeEntry> references)
        {
            return true;
        }

        public abstract PluginProbeEntry Probe(PluginDescriptor descriptor);

        public Plugin Load(PluginDescriptor descriptor)
        {
            var dependency = this.dependenciesFolder.GetDescriptor(descriptor.Id);
            if (dependency != null && dependency.LoaderName == this.Name)
            {
                return this.LoadWorker(descriptor);
            }
            return null;
        }

        public virtual void ReferenceActivated(PluginLoadingContext context, PluginReferenceProbeEntry referenceEntry) { }

        public virtual void ReferenceDeactivated(PluginLoadingContext context, PluginReferenceProbeEntry referenceEntry) { }

        public virtual void PluginActivated(PluginLoadingContext ctx, PluginDescriptor extension) { }

        public virtual void PluginDeactivated(PluginLoadingContext ctx, PluginDescriptor extension) { }

        public virtual void PluginRemoved(PluginLoadingContext ctx, DependencyDescriptor dependency) { }

        public virtual IEnumerable<PluginCompilationReference> GetCompilationReferences(DependencyDescriptor dependency)
        {
            return Enumerable.Empty<PluginCompilationReference>();
        }

        public virtual IEnumerable<string> GetVirtualPathDependencies(DependencyDescriptor dependency) 
        {
            return Enumerable.Empty<string>();
        }

        protected abstract Plugin LoadWorker(PluginDescriptor descriptor);
    }
}
